﻿using System;
using System.Linq;
using System.Diagnostics.Contracts;
using IMModel.Domain.Common;
using System.Collections.Generic;

namespace IMModel.Domain
{
    /// <summary>
    /// Ответ респондента
    /// </summary>
    partial class Answer
    {
        /// <summary>
        /// Получает признак, что этот ответ дан респондентом, который является участником индексной системы
        /// </summary>
        public bool IsRespondentParticipant
        {
            get
            {
                Contract.Requires(Respondent != null);
                return Respondent.IsParticipantInTerm(this.Respondent.Term);
            }
        }

        /// <summary>
        /// Получает признак, что этот ответ дан респондентом, который является участником индексной системы в указанном периоде
        /// </summary>
        /// <param name="term">Период</param>
        /// <returns>Истина, если ответ дан участником индексной системы</returns>
        public bool IsParticipantInTerm(Term term)
        {
            Contract.Requires(Respondent != null);
            return Respondent.IsParticipantInTerm(term);
        }

        /// <summary>
        /// Получает признак того, что данный ответ является оценкой деятельности респондента
        /// </summary>
        public bool IsMark
        {
            get 
            {
                //return false;
                return CharacteristicTerm.IsMark;
                //return false; // GradationCharacteristic != null && GradationCharacteristic.IsMark;
            }
        }

        /// <summary>
        /// Получает значение объём показателя * вес градации
        /// </summary>
        public double Value
        {
            get
            {
                return CalcGradationWeight() * Volume;

                //return 1;
                
                /*
                if (GradationCharacteristic.HasWeight)
                    return Volume * GradationCharacteristic.Weight;
                else
                    return Volume;
                */
            }
        }

        public Domain.Respondent GetRespondentInOtherTerm(Term term)
        {
            Contract.Requires(term!=null);
            return Respondent.GetMeInOtherTerm(term);
        }

        internal double GradVolume
        {
            get
            {
                return GradationsAnswers.Any() ?
                    GradationsAnswers.Sum(x => x.Volume ?? 1) : 1;
            }
        }
        internal double CalcGradationWeight()
        {
            double result = 1;

            foreach (GradationsAnswer ga in GradationsAnswers)
            {
                result *= (ga.Volume ?? 1) * CalcGradationWeightRecursive(ga.GradationTerm);
            }
            return result;
        }

        private double CalcGradationWeightRecursive(GradationTerm gt)
        {
            double result = 1;
            if (gt.IDParentGradationTerm == null) // ! Описать в ДП
                result *= (gt.Weight ?? 1);
            else
                result *= (gt.Weight ?? 1) * CalcGradationWeightRecursive(gt.GradationTerm1);
            return result;
        }

        public bool LastAnswer
        {
            get
            {
                return IsDeleted == false && Answers.Count == 0;
            }
        }
    }
}
